package com.headwind.logistics.common.shiro;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import com.headwind.logistics.common.pojo.Menu;
import com.headwind.logistics.permission.service.intl.EmployeeServiceIntl;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Configuration
public class ShiroConfig {

    @Autowired
    private EmployeeServiceIntl employeeServiceIntl;

    /**
     *这是个自定义的认证类，继承子AuthorizingRealm，负责用户的认证和权限处理
     */
    @Bean
    @DependsOn("lifecycleBeanPostProcessor")
    public MyShiroRealm shiroRealm(){
        MyShiroRealm realm = new MyShiroRealm();
        //realm.setCredentialsMatcher(hashedCredentialsMatcher());
        return realm;
    }

    /** 安全管理器
     * 将realm加入securityManager
     * @return
     */
    @Bean
    public SecurityManager securityManager(){
        //注意是DefaultWebSecurityManager！！！
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(shiroRealm());
        //注入记住我管理器
        securityManager.setRememberMeManager(rememberMeManager());
        return securityManager;
    }

    /** shiro filter 工厂类
     * 1.定义ShiroFilterFactoryBean
     * 2.设置SecurityManager
     * 3.配置拦截器
     * 4.返回定义ShiroFilterFactoryBean
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager,RememberMeFilter rememberMeFilter){
        //1
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

        //2
        //注册securityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        //3
        // 拦截器+配置登录和登录成功之后的url
        //LinkHashMap是有序的，shiro会根据添加的顺序进行拦截
        Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
        //配置不会被拦截的连接  这里顺序判断
        //anon，所有的url都可以匿名访问
        //authc：所有url都必须认证通过才可以访问
        //user，配置记住我或者认证通过才能访问
        //logout，退出登录
        filterChainDefinitionMap.put("/static/**","anon");
        //后台登录
        filterChainDefinitionMap.put("/adminLogin","anon");
        //前台首页
        filterChainDefinitionMap.put("/","anon");
        //前台首页
        filterChainDefinitionMap.put("/index","anon");
        //前台登录
        filterChainDefinitionMap.put("/toLogin","anon");
        //临时登录放开url
        filterChainDefinitionMap.put("/admin/tempQueryEmp","anon");
        //授权
        //循环进行授权拦截
        List<Menu> menuList = employeeServiceIntl.queryMenuPermsByEmpId(null);

        for (Menu menu : menuList) {
            if (menu.getMenuUrl()!=null && !menu.getMenuUrl().trim().equals("")
                    && menu.getPerms()!=null && !menu.getPerms().trim().equals("")){

                filterChainDefinitionMap.put(menu.getMenuUrl(),"perms["+menu.getPerms()+"]");

            }
        }

        //filterChainDefinitionMap.put("/add","perms[用户管理]");

        //过滤连接自定义，从上往下顺序执行，所以用LinkHashMap /**放在最下边
        filterChainDefinitionMap.put("/admin/**", "rememberMe,user");
        //设置登录界面，如果不设置为寻找web根目录下的文件
        //shiroFilterFactoryBean.setLoginUrl("/admin/tempLogin");    //临时登录界面
        shiroFilterFactoryBean.setLoginUrl("/admin/login");
        //设置登录成功后要跳转的连接
        shiroFilterFactoryBean.setSuccessUrl("/admin/index");
        //设置登录未成功，也可以说无权限界面
        shiroFilterFactoryBean.setUnauthorizedUrl("/403");
        //设置授权拦截跳转页面
        shiroFilterFactoryBean.setUnauthorizedUrl("/admin/index");

        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        //配置记住我自定义过滤器
        Map<String, Filter> filter = new HashMap<>();
        filter.put("rememberMe",rememberMeFilter);
        shiroFilterFactoryBean.setFilters(filter);
        //4
        //返回
        return shiroFilterFactoryBean;
    }

    /**
     * cookie对象;
     * rememberMeCookie()方法是设置Cookie的生成模版，比如cookie的name，cookie的有效时间等等。
     * @return
     */
    @Bean
    public SimpleCookie rememberMeCookie(){
        //System.out.println("ShiroConfiguration.rememberMeCookie()");
        //这个参数是cookie的名称，对应前端的checkbox的name = rememberMe
        SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
        //<!-- 记住我cookie生效时间7天 ,单位秒;-->
        simpleCookie.setMaxAge(25200);
        return simpleCookie;
    }

    /**
     * cookie管理对象;
     * rememberMeManager()方法是生成rememberMe管理器，而且要将这个rememberMe管理器设置到securityManager中
     * @return
     */
    @Bean
    public CookieRememberMeManager rememberMeManager(){
        //System.out.println("ShiroConfiguration.rememberMeManager()");
        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
        cookieRememberMeManager.setCookie(rememberMeCookie());
        //rememberMe cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位)
        cookieRememberMeManager.setCipherKey(Base64.decode("2AvVhdsgUs0FSA3SDFAdag=="));
        return cookieRememberMeManager;
    }
    @Bean
    public RememberMeFilter getRememberMeFilter(){
        return new RememberMeFilter();
    }

    /**
     *用于thymeleaf与shiro配合使用
     * @return
     */
    @Bean
    public ShiroDialect getShiroDialect(){

        return new ShiroDialect();
    }
}
